package icu.guodapeng.oauth2.service.impl

import icu.guodapeng.oauth2.domain.user.SecurityUser
import icu.guodapeng.oauth2.domain.user.dto.UserDto
import icu.guodapeng.oauth2.domain.user.enum.MessageConstant
import org.springframework.security.authentication.AccountExpiredException
import org.springframework.security.authentication.CredentialsExpiredException
import org.springframework.security.authentication.DisabledException
import org.springframework.security.authentication.LockedException
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Service
import java.util.stream.Collectors


@Service
class UserServiceImpl : UserDetailsService {

    private val userList: MutableList<UserDto> = ArrayList()

    // @Resource
    // lateinit var passwordEncoder: PasswordEncoder
    private val passwordEncoder: PasswordEncoder by lazy {
        BCryptPasswordEncoder()
    }

    init {
        val pass: String = passwordEncoder.encode("123456")
        userList.add(UserDto(1L, "user", pass, 1, listOf("USER")))
        userList.add(UserDto(2L, "admin", pass, 1, listOf("ADMIN")))
        userList.add(UserDto(3L, "gdp", pass, 1, listOf("USER", "ADMIN")))
    }

    override fun loadUserByUsername(username: String?): UserDetails {
        val findUserList = userList.stream().filter { it.username == username }.collect(Collectors.toList())
        if (findUserList.isEmpty()) throw UsernameNotFoundException(MessageConstant.USERNAME_PASSWORD_ERROR.msg)
        val securityUser = SecurityUser(findUserList[0])
        when (true) {
            !securityUser.isEnabled -> throw DisabledException(MessageConstant.ACCOUNT_DISABLED.msg)
            !securityUser.isAccountNonExpired -> throw AccountExpiredException(MessageConstant.ACCOUNT_EXPIRED.msg)
            !securityUser.isAccountNonLocked -> throw LockedException(MessageConstant.ACCOUNT_LOCKED.msg)
            !securityUser.isCredentialsNonExpired -> throw CredentialsExpiredException(MessageConstant.CREDENTIALS_EXPIRED.msg)
        }
        return securityUser
    }
}
